package com.autonavi.yunda.yunji.common.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.autonavi.yunda.yunji.core.engine.exception.EngineException;
import com.autonavi.yunda.yunji.core.utils.diling.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

@Slf4j
public class TimeUtils {

    public static final String YYYYMMDD_HHMMSS = "yyyy-MM-dd HH:mm:ss";

    public static final String HHMMSS = "HH:mm:ss";

    public static final String YYYYMMDD = "yyyy-MM-dd";

    public static final String YYYYMMDDWITHOUTLINE = "yyyyMMdd";

    public static final int MILLIONS_PER_DAY = 24 * 60 * 60 * 1000;

    /**
     * 将字符串日期转换称long类型
     *
     * @param date
     * @return
     */
    public static String getDate(String date, int interval) {
        Date d = stringToDate(date, YYYYMMDD);
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) + interval);
        return parseDate(c.getTime(), YYYYMMDD);
    }

    /**
     * 将Date类型的时间格式人成format类型字符串
     *
     * @param date
     * @return
     */
    public static String parseDate(Date date, String format) {
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return sf.format(date);
    }

    /**
     * 字符串转换为日期类型
     *
     * @param date
     * @return
     */
    public static Date parseDate(String date) {
        return stringToDate(date, YYYYMMDD);
    }

    /**
     * 字符串转换为日期类型
     *
     * @param date
     * @return
     */
    public static String parseDateToString(String date) {
        Date d = parseDate(date);
        return parseDate(d, YYYYMMDD);
    }

    /**
     * 转换为时间
     * 以当前日期为基准,将time加入到日期中,并转换为long类型
     *
     * @param time
     * @return
     */
    public static long parseTime(String time) {
        String d = parseDate(new Date(), YYYYMMDD);
        return getDate(d, time);
    }

    /**
     * 获取两个日期之间的天数
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static int getInterval(String startDate, String endDate) {
        return getInterval(startDate, endDate, YYYYMMDD);
    }

    public static int getInterval(String startDate, String endDate, String format) {
        Date start = stringToDate(startDate, format);

        Date end = stringToDate(endDate, format);

        Long betweenDays = (end.getTime() - start.getTime()) / MILLIONS_PER_DAY;
        return betweenDays.intValue();
    }

    public static long convertTime(String time) {
        String prefix = time.substring(0, time.length() - 3);
        String suffix = time.substring(time.length() - 3);
        if ("day".equalsIgnoreCase(suffix)) {
            return Long.parseLong(prefix);
        } else if ("hour".equalsIgnoreCase(suffix)) {
            return Long.parseLong(prefix) * 60 * 60 * 1000;
        } else if ("min".equalsIgnoreCase(suffix)) {
            return Long.parseLong(prefix) * 60 * 1000;
        } else if ("sec".equalsIgnoreCase(suffix)) {
            return Long.parseLong(prefix) * 1000;
        }
        return 0L;
    }

    public static Date stringToDate(String str, String type) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(type);
        Date date = null;
        try {
            date = dateFormat.parse(str);
        } catch (Exception e) {
            log.error("日期转换异常,", e);
        }
        return date;
    }

    /**
     * 将mm级时间转换为日期
     */
    public static Integer monthToInt(Date date) {

        SimpleDateFormat fm = new SimpleDateFormat("yyyyMM");
        Long time = date.getTime();
        String datetime = fm.format(new Date(time));
        return Integer.parseInt(datetime);
    }

    /**
     * 将mm级时间转换为日期
     */
    public static Integer dateToInt(Date date) {

        SimpleDateFormat fm = new SimpleDateFormat("yyyyMMdd");
        Long time = date.getTime();
        String datetime = fm.format(new Date(time));
        return Integer.parseInt(datetime);
    }

    /**
     * 将mm级时间转换为日期
     */
    public static Integer dateHourToInt(Date date) {

        SimpleDateFormat fm = new SimpleDateFormat("yyyyMMddHH");
        Long time = date.getTime();
        String datetime = fm.format(new Date(time));
        return Integer.parseInt(datetime);
    }

    //获取theDate 只前或者后的日期
    public static String getFormatDateBaseBrfore(Date theDate, int days) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(theDate);
        cal.add(Calendar.DATE, -1 * days);//传正数，往前推
        return new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
    }

    /**
     * 将mm级时间转换为日期
     */
    public static String dateToD(Date date) {

        SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd");
        Long time = date.getTime();
        String datetime = fm.format(new Date(time));
        return datetime;
    }

    /**
     * 将ss级时间转换为日期
     */
    public static String dateToH(Date date) {

        SimpleDateFormat fm = new SimpleDateFormat("HH:mm:ss");
        Long time = date.getTime();
        String datetime = fm.format(new Date(time));
        return datetime;
    }

    /**
     * 获取日期中的小时
     */
    public static String getHour(Date date) {

        SimpleDateFormat fm = new SimpleDateFormat("HH");
        Long time = date.getTime();
        String datetime = fm.format(new Date(time));
        return datetime;
    }

    public static long getDate(String date, String time) {
        SimpleDateFormat sf = new SimpleDateFormat(YYYYMMDD_HHMMSS);
        Date d = null;
        try {
            if (StringUtils.isBlank(date) || StringUtils.isBlank(time)) {
                d = new Date();
            } else {
                d = sf.parse(date + " " + time);
            }
        } catch (ParseException e) {
            log.error("date:" + date + ", time:" + time + "。日期转换异常,", e);
        }
        return d.getTime();
    }

    /**
     * 返回FormatStr格式的当前时间，"yyyy-MM-dd HH:mm:ss"
     */
    public static String getDateStr(String formatStr) {
        long currentTime = System.currentTimeMillis();
        Date dateNow = new Date(currentTime);
        return getDateStr(dateNow, formatStr);
    }

    /**
     * 返回FormatStr格式的当前时间前seconds秒的时间，"yyyy-MM-dd HH:mm:ss"
     */
    public static String getDateStr(String formatStr, long seconds) {
        long currentTime = System.currentTimeMillis() - seconds * 1000;
        Date dateNow = new Date(currentTime);
        return getDateStr(dateNow, formatStr);
    }

    /**
     * 将date转化为formatStr格式的时间
     */
    public static String getDateStr(Date date, String formatStr) {
        SimpleDateFormat formatter = new SimpleDateFormat(formatStr);
        return formatter.format(date);
    }

    /**
     * 加上指定小时
     *
     * @param hour
     * @return
     */
    public static long hourToMills(int hour) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, hour);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        return c.getTimeInMillis();
    }

    public static String getCurrentTime(String dateFormatStr) {
        if ("".equals(dateFormatStr)) {
            dateFormatStr = "yyyyMMddHHmmss";
        }
        //得到long类型当前时间
        long l = System.currentTimeMillis();
        //new日期对象
        Date date = new Date(l);
        //转换提日期输出格式
        SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
        return dateFormat.format(date);
    }

    /**
     * 日期转换成字符串
     *
     * @param date
     * @return str
     */
    public static String dateToStr(Date date) {

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String str = format.format(date);
        return str;
    }

    public static String getTimeRandom() {
        String key = System.currentTimeMillis() + "_" + (int)(Math.random() * 10000);
        //1541065878749_9999
        return key;
    }

    public static Double getReduceTime(Long startTime, Long endTime) {
        long timeLong = endTime - startTime;
        double timeDouble = Double.parseDouble(Long.toString(timeLong));
        return timeDouble / (double)1000;
    }

    /**
     * time如果为空，返回前一小时时间，time格式yyyyMMddhh
     *
     * @param time
     * @return yyyyMMddhh
     */
    public static String checkTimeFormat(String time) throws EngineException {
        if (com.alibaba.security.util.StringUtils.isEmpty(time)) {
            time = TimeUtils.getDateStr("yyyyMMddHH", 3600);
        } else {
            if (!time.matches("\\d{10}")) {
                throw new EngineException("5", "time is illegal,Format is yyyyMMddHH");
            }
            //时间小于当时时间，且是两天内的时间
            Date dateTime = TimeUtils.stringToDate(time, "yyyyMMddHH");
            if (dateTime.getTime() >= System.currentTimeMillis()
                || dateTime.getTime() < System.currentTimeMillis() - 48 * 3600 * 1000) {
                throw new EngineException("5", "time must within 2 days and before current time");
            }
        }
        return time;
    }

    /**
     * 获取时间范围内的时间值
     *
     * @param startTimeStr：时分 如1030或者30
     * @param endTimeStr：时分   如1030或者30，可以跨天小于startTime
     * @param minStepO：分钟步长
     * @return array<Integer>
     */
    public static List<Integer> getTimeArr(String startTimeStr, String endTimeStr, Object minStepO)
        throws EngineException {

        int minStep = 15;
        if (ObjectUtil.isNotEmpty(minStepO)) {
            minStep = Integer.parseInt(minStepO.toString());
        }

        List<Integer> timeData = new ArrayList<>();

        int startTime = getTimeMinute(startTimeStr);
        int endTime = getTimeMinute(endTimeStr);

        int i = 0;
        int dayMunite = 1440;
        if (endTime < startTime) {
            endTime += dayMunite;
        }
        while (startTime <= endTime) {

            int minuteNum = startTime;
            if (startTime >= dayMunite) {
                minuteNum -= dayMunite;
            }
            int hour = minuteNum / 60;
            int minute = minuteNum % 60;
            int addTime = 100 * hour + minute;
            timeData.add(addTime);
            //			System.out.println("addTime:"+addTime);

            startTime += minStep;
            if (++i > dayMunite) {
                break;
            }
        }
        return timeData;
    }

    public static int getTimeMinute(String hourMinute) throws EngineException {

        if (hourMinute == null) {
            throw new EngineException("1003", "time null error!");
        }
        int timeInt;
        try {
            timeInt = Integer.parseInt(hourMinute);
        } catch (Exception e) {
            throw new EngineException("1003", "time is not int error!");
        }
        String hourMinuteStr = String.format("%04d", timeInt);
        return Integer.parseInt(hourMinuteStr.substring(0, 2)) * 60 + Integer.parseInt(hourMinuteStr.substring(2));
    }

    /**
     * 获取两个日期范围内的所有周末或当月的月末
     *
     * @param dateType  日期类型(1代表周；2代表月)
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return
     */
    public static List<String> getWeekOrMonthDiff(int dateType, String startDate, String endDate) {
        List<String> dateList = new LinkedList<>();
        if (StringUtils.isAnyBlank(startDate, endDate)) {
            return dateList;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TimeUtils.YYYYMMDDWITHOUTLINE);
        //将startDate,endDate格式化为localDate类型
        LocalDate startLocalDate = LocalDate.parse(startDate, formatter);
        LocalDate endLocalDate = LocalDate.parse(endDate, formatter);
        //当dateType=2时，获取startLocalDate日期的该月月末
        if (2 == dateType) {
            startLocalDate = startLocalDate.with(TemporalAdjusters.lastDayOfMonth());
        }
        while (startLocalDate.compareTo(endLocalDate) <= 0) {
            if (0 == dateType) {
                dateList.add(startLocalDate.format(DateTimeFormatter.BASIC_ISO_DATE));
                startLocalDate = startLocalDate.plusDays(1);
            } else if (1 == dateType) {
                if (startLocalDate.getDayOfWeek().equals(DayOfWeek.SUNDAY)) {
                    String dateStr = startLocalDate.format(DateTimeFormatter.BASIC_ISO_DATE);
                    dateList.add(dateStr);
                }
                startLocalDate = startLocalDate.plusDays(1);
            } else if (2 == dateType) { //获取所有月末
                String dateStr = startLocalDate.format(DateTimeFormatter.BASIC_ISO_DATE);
                dateList.add(dateStr);
                //获取下个月的月末
                startLocalDate = startLocalDate.plusDays(1).with(TemporalAdjusters.lastDayOfMonth());
            }
        }
        return dateList;
    }

}
